package com.worthtech.portal.web.taglib;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.jsp.JspException;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.IteratorUtils;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.taglib.html.BaseHandlerTag;
import org.apache.struts.taglib.html.Constants;
import org.apache.struts.util.MessageResources;

public class CheckboxTag extends BaseHandlerTag {
	// ----------------------------------------------------- Instance Variables
	/**
	 * The message resources for this package.
	 */
	protected static MessageResources messages = MessageResources
			.getMessageResources(Constants.Package + ".LocalStrings");

	/**
	 * The name of the bean containing our underlying property.
	 */
	protected String name = Constants.BEAN_KEY;

	public String getName() {
		return (this.name);
	}

	public void setName(String name) {
		this.name = name;
	}

	/**
	 * The property name for this field.
	 */
	protected String property = null;

	/**
	 * The body content of this tag (if any).
	 */
	protected String text = null;

	/**
	 * The server value for this option.
	 */
	protected String value = null;

	private String valueName = null;

	private String valueProperty = null;

	private String collection = null;

	// private Iterator collIterator;

	// ------------------------------------------------------------- Properties

	/**
	 * Return the property name.
	 */
	public String getProperty() {

		return (this.property);

	}

	/**
	 * Set the property name.
	 * 
	 * @param property
	 *            The new property name
	 */
	public void setProperty(String property) {

		this.property = property;

	}

	/**
	 * Return the server value.
	 */
	public String getValue() {

		return (this.value);

	}

	public String getValueName() {
		return valueName;
	}

	public String getValueProperty() {
		return valueProperty;
	}

	public String getCollection() {
		return collection;
	}

	/**
	 * Set the server value.
	 * 
	 * @param value
	 *            The new server value
	 */
	public void setValue(String value) {

		this.value = value;

	}

	public void setValueName(String valueName) {
		this.valueName = valueName;
	}

	public void setValueProperty(String valueProperty) {
		this.valueProperty = valueProperty;
	}

	public void setCollection(String collection) {
		this.collection = collection;
	}

	// --------------------------------------------------------- Public Methods

	/**
	 * Generate the required input tag.
	 * <p>
	 * Support for indexed property since Struts 1.1
	 * 
	 * @exception JspException
	 *                if a JSP exception has occurred
	 */
	public int doStartTag() throws JspException {
		// if (this.collection != null) {
		// this.collIterator = getIterator(collection, null);
		// }
		// Create an appropriate "input" element based on our parameters
		StringBuffer results = new StringBuffer("<input type=\"checkbox\"");
		results.append(" name=\"");

		if (indexed) {
			prepareIndex(results, name);
		}

		results.append(this.property);
		results.append("\"");
		if (accesskey != null) {
			results.append(" accesskey=\"");
			results.append(accesskey);
			results.append("\"");
		}

		if (tabindex != null) {
			results.append(" tabindex=\"");
			results.append(tabindex);
			results.append("\"");
		}

		results.append(" value=\"");
		value = this.getIterateValue();

		if (value == null) {
			results.append("on");
		} else {
			results.append(value);
		}

		results.append("\"");

		if (this.isChecked()) {
			results.append(" checked=\"checked\"");
		}

		results.append(prepareEventHandlers());
		results.append(prepareStyles());
		results.append(getElementClose());

		// Print this field to our output writer
		TagUtils.getInstance().write(pageContext, results.toString());

		// Continue processing this page
		this.text = null;
		return (EVAL_BODY_TAG);
		// return this.EVAL_BODY_BUFFERED;
	}

	/**
	 * Determines if the checkbox should be checked.
	 * 
	 * @return true if checked="checked" should be rendered.
	 * @throws JspException
	 * @since Struts 1.2
	 */
	protected boolean isChecked() throws JspException {
			String nowValue = this.getIterateValue();
			Iterator collIterator = getIterator(collection, null);
			// System.out.println(collIterator);
			while (collIterator.hasNext()) {
				// System.out.println("");
				Object bean = collIterator.next();
				// System.out.println("bean:" + bean);
				com.worthtech.billportal.bean.Permission permission = (com.worthtech.billportal.bean.Permission)bean;
				if (nowValue.equals(String.valueOf(permission.getId()))) {
					return true;
				}
			}
			collIterator = null;
			return false;
	}

	protected String getIterateValue() throws JspException {
		if (this.valueName != null && this.valueProperty != null) {
			Object iValue = TagUtils.getInstance().lookup(pageContext,valueName, valueProperty, null);
			if (iValue == null) {
				return this.value;
			}
			return iValue.toString();
		} else {
			return this.value;
		}
	}

	/**
	 * Return an iterator for the option labels or values, based on our
	 * configured properties.
	 * 
	 * @param name
	 *            Name of the bean attribute (if any)
	 * @param property
	 *            Name of the bean property (if any)
	 * 
	 * @exception JspException
	 *                if an error occurs
	 */
	protected Iterator getIterator(String name, String property)
			throws JspException {

		// Identify the bean containing our collection
		String beanName = name;
		if (beanName == null) {
			beanName = Constants.BEAN_KEY;
		}
		Object bean = new Object();
		bean = TagUtils.getInstance().lookup(pageContext, beanName, null);
		if (bean == null) {
			throw new JspException(messages.getMessage("getter.bean", beanName));
		}

		// Identify the collection itself
		Object collection = bean;
		if (property != null) {
			try {
				collection = PropertyUtils.getProperty(bean, property);
				if (collection == null) {
					throw new JspException(messages.getMessage(
							"getter.property", property));
				}
			} catch (IllegalAccessException e) {
				throw new JspException(messages.getMessage("getter.access",
						property, name));
			} catch (InvocationTargetException e) {
				Throwable t = e.getTargetException();
				throw new JspException(messages.getMessage("getter.result",
						property, t.toString()));
			} catch (NoSuchMethodException e) {
				throw new JspException(messages.getMessage("getter.method",
						property, name));
			}
		}

		// Construct and return an appropriate iterator
		if (collection.getClass().isArray()) {
			collection = Arrays.asList((Object[]) collection);
		}

		if (collection instanceof Collection) {
			return (((Collection) collection).iterator());

		} else if (collection instanceof Iterator) {
			return ((Iterator) collection);

		} else if (collection instanceof Map) {
			return (((Map) collection).entrySet().iterator());

		} else if (collection instanceof Enumeration) {
			return IteratorUtils.asIterator((Enumeration) collection);

		} else {
			throw new JspException(messages.getMessage("optionsTag.iterator",
					collection.toString()));
		}
	}

	protected Object[] getObjArray(String name, String property)
			throws JspException {

		// Identify the bean containing our collection
		String beanName = name;
		if (beanName == null) {
			beanName = Constants.BEAN_KEY;
		}
		Object bean = new Object();
		bean = TagUtils.getInstance().lookup(pageContext, beanName, null);
		if (bean == null) {
			throw new JspException(messages.getMessage("getter.bean", beanName));
		}

		// Identify the collection itself
		Object collection = bean;
		if (property != null) {
			try {
				collection = PropertyUtils.getProperty(bean, property);
				if (collection == null) {
					throw new JspException(messages.getMessage(
							"getter.property", property));
				}
			} catch (IllegalAccessException e) {
				throw new JspException(messages.getMessage("getter.access",
						property, name));
			} catch (InvocationTargetException e) {
				Throwable t = e.getTargetException();
				throw new JspException(messages.getMessage("getter.result",
						property, t.toString()));
			} catch (NoSuchMethodException e) {
				throw new JspException(messages.getMessage("getter.method",
						property, name));
			}
		}

		// Construct and return an appropriate iterator
		// if (collection.getClass().isArray()) {
		// collection = Arrays.asList( (Object[]) collection);
		// }

		return (Object[]) collection;
	}

	/**
	 * Save the associated label from the body content.
	 * 
	 * @exception JspException
	 *                if a JSP exception has occurred
	 */
	public int doAfterBody() throws JspException {

		if (bodyContent != null) {
			String value = bodyContent.getString().trim();
			if (value.length() > 0) {
				text = value;
			}
		}
		return (SKIP_BODY);

	}

	/**
	 * Process the remainder of this page normally.
	 * 
	 * @exception JspException
	 *                if a JSP exception has occurred
	 */
	public int doEndTag() throws JspException {

		// Render any description for this checkbox
		if (text != null) {
			TagUtils.getInstance().write(pageContext, text);
		}

		// Evaluate the remainder of this page
		return (EVAL_PAGE);

	}

	/**
	 * Release any acquired resources.
	 */
	public void release() {
		super.release();
		name = Constants.BEAN_KEY;
		property = null;
		text = null;
		value = null;

	}

}
